#include <stdio.h>      // 提供 fgetc、fputc、stdin、stdout 等输入输出函数
#include <pthread.h>    // 提供 pthread_create、pthread_join、pthread_t 等线程相关函数
#include <unistd.h>     // 提供 sleep 等系统调用

#define BUFF_LEN 1024   // 定义缓冲区大小

char buf[BUFF_LEN];     // 全局字符缓冲区

// step 1# 声明写线程函数
void *write_thread_run(void *);

// step 2# 声明读线程函数
void *read_thread_run(void *);

int main(int argc, char const *argv[])
{
    // step 3# 声明两个线程 ID，分别用于写线程和读线程
    pthread_t write_thread;  // 用于保存写线程ID
    pthread_t read_thread;   // 用于保存读线程ID

    // step 4# 创建写线程，执行 write_thread_run
    pthread_create(&write_thread, NULL, write_thread_run, NULL);  // 创建写线程

    // step 5# 创建读线程，执行 read_thread_run
    pthread_create(&read_thread, NULL, read_thread_run, NULL);    // 创建读线程

    // step 6# 主线程等待两个子线程结束（阻塞）
    pthread_join(write_thread, NULL);  // 等待写线程执行完毕
    pthread_join(read_thread, NULL);   // 等待读线程执行完毕

    return 0;
}

// step 7# 写线程运行函数：从标准输入读取字符写入共享缓冲区
void *write_thread_run(void *argv){
    int i = 0;
    char c;

    while (1) {
        c = fgetc(stdin);  // 从标准输入读取一个字符
        if (c && c != '\n') {     // 忽略换行和无效字符
            buf[i++] = c;         // 写入缓冲区
            if (i >= BUFF_LEN) {
                i = 0;            // 如果索引溢出，从头开始写
            }
        }
    }
}

// step 8# 读线程运行函数：从共享缓冲区读取字符并输出
void *read_thread_run(void *argv){
    int i = 0;
    char c;

    while (1) {
        if (buf[i]) {                     // 判断当前位置是否有数据
            fputc(buf[i], stdout);        // 输出一个字符
            fputc('\n', stdout);          // 输出换行
            buf[i++] = 0;                 // 清空已读数据
            if (i >= BUFF_LEN) {
                i = 0;                    // 如果索引溢出，从头开始读
            }
        } else {
            sleep(1);                     // 没数据时等待 1 秒
        }
    }
}
